package com.ruifu.bom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fhzncloud.cloud.common.security.service.CloudUser;
import com.fhzncloud.cloud.common.security.util.SecurityUtils;
import com.ruifu.bom.dto.*;
import com.ruifu.bom.mapper.MaterielMapper;
import com.ruifu.bom.mapper.MaterielStructureMapper;
import com.ruifu.bom.mapper.MaterielTypeMapper;
import com.ruifu.bom.mapper.MaterielVersionsMapper;
import com.ruifu.bom.service.MaterielVersionsService;
import com.ruifu.bom.vo.MaterielAndVersionsVO;
import com.ruifu.bom.vo.MaterielVersionsHistoryVO;
import com.ruifu.common.eneity.BaseEntityPlus;
import com.ruifu.common.po.Materiel;
import com.ruifu.common.po.MaterielStructure;
import com.ruifu.common.po.MaterielType;
import com.ruifu.common.po.MaterielVersions;
import com.ruifu.common.utils.BeanConverter;
import com.ruifu.common.utils.StrUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 物料业务逻辑层实现类
 *
 * @author nyr
 * @create 2019/12/19
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class MaterielVersionsServiceImpl extends ServiceImpl<MaterielVersionsMapper, MaterielVersions> implements MaterielVersionsService {
    @Autowired(required = false)
    private MaterielVersionsMapper materielVersionsMapper;

    @Autowired(required = false)
    private MaterielMapper materielMapper;

    @Autowired(required = false)
    private MaterielTypeMapper materielTypeMapper;

    @Autowired(required = false)
    private MaterielStructureMapper structureMapper;

    /**
     * 新建物料(含物料版本)
     *
     * @param materielAndVersionsDTO 物料和物料版本传输对象
     * @return
     */
    @Override
    public R saveMaterielAndVersion(MaterielAndVersionsDTO materielAndVersionsDTO) {
        try {
            //获取物料对象
            MaterielDTO materielDTO = materielAndVersionsDTO.getMaterielDTO();
            //获取物料版本对象
            MaterielVersionsDTO materielVersionsDTO = materielAndVersionsDTO.getMaterielVersionsDTO();
            //设置扩展属性集
            materielVersionsDTO.setMvExtendProperty(StrUtils.upperToLower(materielVersionsDTO.getMvExtendProperty()));
            //设置特征参数集
            materielVersionsDTO.setMvFeatureProperty(StrUtils.upperToLower(materielVersionsDTO.getMvFeatureProperty()));
            //新建物料
            materielMapper.insert(materielDTO);
            //新建物料版本设置物料id
            materielVersionsDTO.setMvMaterielId(materielDTO.getMlId());
            materielVersionsMapper.insert(materielVersionsDTO);
            //设置物料的最新版本id(MvId 版本id)
            materielDTO.setMlNewVersionId(materielVersionsDTO.getMvId());
            materielMapper.updateById(materielDTO);
            return R.ok("物料新建成功");
        } catch (Exception e) {
            e.printStackTrace();
            return R.failed("新建失败");
        }
    }

    /**
     * 修改物料(含物料版本)
     *
     * @param materielAndVersionsDTO 物料和物料版本传输对象
     * @return
     */
    @Override
    public R updateMaterielAndVersion(MaterielAndVersionsDTO materielAndVersionsDTO) {
        //获取物料对象
        MaterielDTO materielDTO = materielAndVersionsDTO.getMaterielDTO();
        //获取物料版本对象
        MaterielVersionsDTO materielVersionsDTO = materielAndVersionsDTO.getMaterielVersionsDTO();
        //设置扩展属性集
        materielVersionsDTO.setMvExtendProperty(StrUtils.upperToLower(materielVersionsDTO.getMvExtendProperty()));
        //设置特征参数集
        materielVersionsDTO.setMvFeatureProperty(StrUtils.upperToLower(materielVersionsDTO.getMvFeatureProperty()));
        //修改物料
        materielMapper.updateById(materielDTO);
        //修改物料版本
        materielVersionsMapper.updateById(materielVersionsDTO);
        return R.ok("物料修改成功");
    }

    /**
     * 删除物料(含物料版本)
     *
     * @param mvIds 物料版本id集合
     * @return
     */
    @Override
    public R batchDelete(List<Long> mvIds) {
        if (mvIds != null && mvIds.size() != 0) {
            //根据物料版本id批量查询物料
            List<Long> mlMaterielIds = materielVersionsMapper.selectBatchIds(mvIds)
                    .stream()
                    .map(MaterielVersions::getMvMaterielId)
                    .collect(Collectors.toList());
            //删除物料
            materielMapper.deleteBatchIds(mlMaterielIds);
            //删除版本
            materielVersionsMapper.deleteBatchIds(mvIds);
            //查询物料是否被引用
            List<MaterielStructure> materielStructureList = structureMapper.selectList(Wrappers.<MaterielStructure>lambdaQuery().eq(MaterielStructure::getStMaterielId, mvIds));
            if (materielStructureList != null && materielStructureList.size() != 0) {
                //提取子项物料id集合
                List<Long> materielIds = materielStructureList.stream().map(MaterielStructure::getStMaterielId).collect(Collectors.toList());
                //删除物料引用
                structureMapper.delete(new QueryWrapper<MaterielStructure>().lambda().eq(MaterielStructure::getStMaterielId, materielIds));
            }
        }
        return R.ok("物料删除成功");
    }

    /**
     * 升级零部件版本
     *
     * @param mvId 物料版本id
     * @return
     */
    @Override
    //TODO 升级零部件版本需要对其关联的BOM级联操作！？
    public R upVersion(Long mvId) {
        /*升级版本*/
        //查询物料版本
        MaterielVersions materielVersions = materielVersionsMapper.selectOne(Wrappers.<MaterielVersions>lambdaQuery()
                .eq(MaterielVersions::getMvId, mvId)
                .eq(BaseEntityPlus::getSetSid, SecurityUtils.getUser().getTenantId()));
        MaterielVersions newMaterielVersions = BeanConverter.copyProperties(materielVersions, MaterielVersions.class);
        //判断是否已发布
        if (!"已发布".equals(materielVersions.getMvDesignStatus())) {
            return R.failed("该物料状态未发布,无法升版");
            //判断是否是最新版本
        } else if (!materielVersions.getMvNewVersionFlag()) {
            return R.failed("该物料版本不是最新版本,无法升版");
        }
        materielVersions.setMvNewVersionFlag(false);
        materielVersionsMapper.updateById(materielVersions);
        newMaterielVersions.setMvVersionsOrder(newMaterielVersions.getMvVersionsOrder() + 1);
        newMaterielVersions.setMvDesignStatus("编辑中");
        materielVersionsMapper.insert(newMaterielVersions);
        //修改物料中最新版本id
        Materiel materiel = materielMapper.selectById(materielVersions.getMvMaterielId());
        if (!"p".equals(materiel.getMlClass())) {
            return R.failed(materiel.getMlName() + "不是零部件,无法升版");
        }
        materiel.setMlNewVersionId(newMaterielVersions.getMvId());
        materielMapper.updateById(materiel);
        return R.ok("升版成功");
    }

    /**
     * 查询历史版本
     *
     * @param mvMaterielId 物料id
     * @return
     */
    @Override
    public R versionHistory(Long mvMaterielId) {
        //查询历史版本列表
        MaterielVersions materielVersions = materielVersionsMapper.selectById(mvMaterielId);
        List<MaterielVersions> materielVersionsList = materielVersionsMapper.selectList(Wrappers.<MaterielVersions>lambdaQuery()
                .eq(MaterielVersions::getMvMaterielId, materielVersions.getMvMaterielId())
                .eq(BaseEntityPlus::getSetSid, SecurityUtils.getUser().getTenantId())
                .orderByAsc(MaterielVersions::getMvVersionsOrder));
        List<MaterielVersionsHistoryVO> materielVersionsHistoryVOList = BeanConverter.copyList(materielVersionsList, MaterielVersionsHistoryVO.class);
        //设置物料名称
        materielVersionsHistoryVOList.forEach(materielVersionsHistoryVO -> {
            Materiel materiel = materielMapper.selectById(materielVersionsHistoryVO.getMvMaterielId());
            materielVersionsHistoryVO.setMlName(materiel.getMlName());
        });
        return R.ok(materielVersionsHistoryVOList);
    }

    /**
     * 转交版本所有权
     *
     * @param mvId   版本id
     * @param userId 被转交人
     * @return
     */
    @Override
    public R transferOwnership(Long mvId, Long userId) {
        MaterielVersions materielVersions = materielVersionsMapper.selectById(mvId);
        materielVersions.setCreator(userId);
        materielVersions.setOwner(userId);
        materielVersionsMapper.updateById(materielVersions);
        return R.ok("转交所有权成功");
    }

    /**
     * 联合查询
     *
     * @param page
     * @param materielAndVersionsDTO
     * @param cloudUser
     * @return
     */
    @Override
    public Page<MaterielAndVersionsVO> find(Page<MaterielAndVersionsVO> page, MaterielAndVersionsDTO materielAndVersionsDTO, CloudUser cloudUser) {
        //获取原材料/原材料版本
        List<MaterielVersions> materielVersionsList = materielVersionsMapper.findByQuery(page, materielAndVersionsDTO, cloudUser);
        //PO转VO
        List<MaterielAndVersionsVO> materielAndVersionsVoList = BeanConverter.copyList(materielVersionsList, MaterielAndVersionsVO.class);
        for (MaterielAndVersionsVO materielAndVersionsVO : materielAndVersionsVoList) {
            //判断物料是否绑定模型
            if (materielAndVersionsVO.getMateriel().getMlModelId() != 0 && materielAndVersionsVO.getMateriel().getMlModelId() != null) {
                //查询模型对应的物料版本
                MaterielVersions modelMaterielVersions = materielVersionsMapper.selectById(
                        materielAndVersionsVO.getMateriel().getMlModelId());
                //根据模型对应的id查询对应物料
                Materiel materiel = materielMapper.selectById(modelMaterielVersions.getMvMaterielId());
                //模型名称
                materielAndVersionsVO.setProductModelName(materiel.getMlName());
            }
            if (materielAndVersionsVO.getMateriel().getMlTypeId() != null) {
                MaterielType materielType = materielTypeMapper.selectById(
                        materielAndVersionsVO.getMateriel().getMlTypeId());
                //设置分类名称
                materielAndVersionsVO.setTypeName(materielType.getMtClassName());
                //设置分类代码
                materielAndVersionsVO.setTypeCode(materielType.getMtCode());
            }
        }
        return page.setRecords(materielAndVersionsVoList);
    }

    /**
     * 根据物料版本id查询物料详情
     *
     * @param mvId
     * @return
     */
    @Override
    public R findByMvId(String mvId) {
        //获取版本对象
        MaterielVersions materielVersions = materielVersionsMapper.findByMvId(mvId);
        //获取物料对象
        Materiel materiel = materielVersions.getMateriel();
        MaterielAndVersionsVO materielAndVersionsVO = BeanConverter.copyProperties(materielVersions, MaterielAndVersionsVO.class);

        //获取类型对象
        if (null != materiel.getMlTypeId()) {
            MaterielType materielType = materielTypeMapper.selectById(materielVersions.getMateriel().getMlTypeId());
            //父类型扩展属性
            materielAndVersionsVO.setMtExtendAattribute(materielType.getMtExtendAttribute());
            //设置类型代码
            materielAndVersionsVO.setTypeCode(materielType.getMtCode());
            //设置类型名称
            materielAndVersionsVO.setTypeName(materielType.getMtClassName());
        }

        //获取物料模型id
        if (materiel.getMlModelId() != 0 && materiel.getMlModelId() != null) {
            //根据模型id查询模型版本
            MaterielVersions materielVersion = materielVersionsMapper.selectById(materiel.getMlModelId());
            //获取模型的配置参数
            materielAndVersionsVO.setModelString(materielVersion.getMvFeatureProperty());
        }

        return R.ok(materielAndVersionsVO);
    }

    /**
     * 另存为
     *
     * @param saveAsDTO
     * @return
     */
    @Override
    public R saveAs(SaveAsDTO saveAsDTO) {
        //物料版本对象
        MaterielVersions materielVersions = materielVersionsMapper.selectOne(Wrappers.<MaterielVersions>lambdaQuery()
                .eq(MaterielVersions::getMvId, saveAsDTO.getMvId())
                .eq(BaseEntityPlus::getSetSid, SecurityUtils.getUser().getTenantId()));
        //物料对象
        Materiel materiel = materielMapper.selectById(materielVersions.getMvMaterielId());
        //清空物料主键
        materiel.setMlId(null);
        materiel.setMlName(saveAsDTO.getMlName());
        materiel.setMlCode(saveAsDTO.getMlCode());
        materielMapper.insert(materiel);
        //清空物料版本主键
        materielVersions.setMvId(null);
        //新建物料版本设置物料id(MlId 物料id)
        materielVersions.setMvMaterielId(materiel.getMlId());
        materielVersionsMapper.insert(materielVersions);
        //设置物料的最新版本id
        materiel.setMlNewVersionId(materielVersions.getMvId());
        materielMapper.updateById(materiel);
        return R.ok("另存为成功");
    }

    @Override
    public void saveImport(List<MaterielImportDTO> materielImportDTOList, List<Long> longList) {
        List<MaterielVersions> materielVersionsList = BeanConverter.copyList(materielImportDTOList, MaterielVersions.class);
        int i = 0;
        for (MaterielVersions materielVersions : materielVersionsList) {
            materielVersions.setMvMaterielId(longList.get(i));
            materielVersionsMapper.insert(materielVersions);
            i++;
        }
    }


}